/**
 * 测试娱乐城中奖消息保存到私信表功能
 * 验证修复后的中奖消息是否正确保存到 private_messages 表
 */

const http = require('http');
const WebSocket = require('ws');

// 测试配置
const CONFIG = {
    server: {
        host: 'localhost',
        port: 3001,
        protocol: 'http'
    },

    // 测试用户信息
    testUser: {
        mobile: '17091271111',
        password: '123456',
        passwordHash: 'e10adc3949ba59abbe56e057f20f883e' // 123456的MD5
    }
};

class CasinoPrivateMessageTester {
    constructor() {
        this.token = null;
        this.userId = null;
        this.ws = null;
        this.testResults = [];
        this.characterId = null;
    }

    // 运行完整测试流程
    async runTest() {
        console.log('🎰 开始测试娱乐城中奖消息保存到私信表功能...\n');
        console.log('测试目标：验证中奖消息是否正确保存到 private_messages 表\n');

        try {
            // 1. HTTP登录
            await this.testHttpLogin();

            // 2. 建立WebSocket连接
            await this.testWebSocketConnection();

            // 3. 查询角色列表
            await this.testQueryCharacters();

            // 4. 选择角色
            await this.testSelectCharacter();

            // 5. 等待中奖通知并验证私信表
            await this.testWaitForWinningNotification();

            // 6. 验证私信表中的消息
            await this.testVerifyPrivateMessageInDatabase();

            // 7. 断开连接
            await this.testDisconnect();

            // 输出测试结果
            this.printTestResults();

        } catch (error) {
            console.error('❌ 测试过程中发生错误:', error.message);
            this.addTestResult('整体测试', false, error.message);
        }
    }

    // 1. HTTP登录测试
    async testHttpLogin() {
        console.log('🔐 步骤1: HTTP登录测试...');

        try {
            // 执行登录
            const loginData = await this.makeHttpRequest('/user-service/user/login', 'POST', {
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash
            });

            if (loginData.code === 0 && loginData.data) {
                this.userId = loginData.data.userId;
                this.token = loginData.data.accessToken;

                console.log(`✅ 登录成功: userId=${this.userId}, token=${this.token.substring(0, 8)}...`);
                this.addTestResult('HTTP登录', true, `用户ID: ${this.userId}`);
            } else {
                throw new Error(`登录失败: ${loginData.msg || '未知错误'}`);
            }

        } catch (error) {
            console.log('❌ 登录失败:', error.message);
            this.addTestResult('HTTP登录', false, error.message);
            throw error;
        }
    }

    // 2. WebSocket连接测试
    async testWebSocketConnection() {
        console.log('\n🔌 步骤2: WebSocket连接测试...');

        return new Promise((resolve, reject) => {
            try {
                const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
                this.ws = new WebSocket(wsUrl);

                this.ws.on('open', () => {
                    console.log('✅ WebSocket连接成功');
                    this.addTestResult('WebSocket连接', true, '连接成功');
                    resolve();
                });

                this.ws.on('error', (error) => {
                    console.log('❌ WebSocket连接失败:', error.message);
                    this.addTestResult('WebSocket连接', false, error.message);
                    reject(error);
                });

                this.ws.on('close', () => {
                    console.log('🔌 WebSocket连接已关闭');
                });

                setTimeout(() => {
                    if (this.ws.readyState === WebSocket.CONNECTING) {
                        reject(new Error('WebSocket连接超时'));
                    }
                }, 10000);
            } catch (error) {
                reject(error);
            }
        });
    }

    // 3. 查询角色列表
    async testQueryCharacters() {
        console.log('\n📋 步骤3: 查询角色列表...');

        return new Promise((resolve, reject) => {
            try {
                // 发送查询角色列表请求
                const request = {
                    c: 1001, // 查询角色列表指令
                    d: {}
                };

                this.ws.send(JSON.stringify(request));

                // 等待响应
                const responseHandler = (data) => {
                    try {
                        const message = JSON.parse(data.toString());
                        if (message.c === 1001 && message.code === 0) {
                            this.ws.removeListener('message', responseHandler);

                            if (message.data && message.data.length > 0) {
                                this.characterId = message.data[0].id;
                                console.log(`✅ 查询角色列表成功，选择角色ID: ${this.characterId}`);
                                this.addTestResult('查询角色列表', true, `角色ID: ${this.characterId}`);
                                resolve();
                            } else {
                                throw new Error('角色列表为空');
                            }
                        }
                    } catch (error) {
                        // 忽略解析错误，继续等待
                    }
                };

                this.ws.on('message', responseHandler);

                // 设置超时
                setTimeout(() => {
                    this.ws.removeListener('message', responseHandler);
                    reject(new Error('查询角色列表超时'));
                }, 10000);

            } catch (error) {
                reject(error);
            }
        });
    }

    // 4. 选择角色
    async testSelectCharacter() {
        console.log('\n🎭 步骤4: 选择角色...');

        return new Promise((resolve, reject) => {
            try {
                // 发送选择角色请求
                const request = {
                    c: 1002, // 选择角色指令
                    d: {
                        characterId: this.characterId
                    }
                };

                this.ws.send(JSON.stringify(request));

                // 等待响应
                const responseHandler = (data) => {
                    try {
                        const message = JSON.parse(data.toString());
                        if (message.c === 1002 && message.code === 0) {
                            this.ws.removeListener('message', responseHandler);
                            console.log('✅ 角色选择成功');
                            this.addTestResult('角色选择', true, '选择成功');
                            resolve();
                        }
                    } catch (error) {
                        // 忽略解析错误，继续等待
                    }
                };

                this.ws.on('message', responseHandler);

                // 设置超时
                setTimeout(() => {
                    this.ws.removeListener('message', responseHandler);
                    reject(new Error('角色选择超时'));
                }, 10000);

            } catch (error) {
                reject(error);
            }
        });
    }

    // 5. 等待中奖通知
    async testWaitForWinningNotification() {
        console.log('\n🎉 步骤5: 等待中奖通知...');
        console.log('⚠️  注意：此步骤需要手动触发娱乐城开奖结算才能收到通知');
        console.log('💡 建议：在另一个终端运行娱乐城开奖结算脚本');

        return new Promise((resolve, reject) => {
            let notificationReceived = false;

            const responseHandler = (data) => {
                try {
                    const message = JSON.parse(data.toString());
                    if (message.act_id === 10 && message.info_id === 1000 && message.state === 1) {
                        this.ws.removeListener('message', responseHandler);
                        notificationReceived = true;
                        console.log('🎉 收到中奖系统消息通知！');
                        console.log('📨 消息内容:', JSON.stringify(message, null, 2));
                        this.addTestResult('中奖通知接收', true, '收到中奖通知');
                        resolve();
                    }
                } catch (error) {
                    // 忽略解析错误，继续等待
                }
            };

            this.ws.on('message', responseHandler);

            // 设置超时（5分钟）
            setTimeout(() => {
                this.ws.removeListener('message', responseHandler);
                if (!notificationReceived) {
                    console.log('⏰ 等待超时，未收到中奖通知');
                    console.log('💡 这可能是因为：');
                    console.log('   1. 没有触发娱乐城开奖结算');
                    console.log('   2. 当前角色没有参与下注');
                    console.log('   3. 当前角色没有中奖');
                    this.addTestResult('中奖通知接收', false, '等待超时，未收到通知');
                    resolve(); // 不抛出错误，继续测试
                }
            }, 300000); // 5分钟超时
        });
    }

    // 6. 验证私信表中的消息
    async testVerifyPrivateMessageInDatabase() {
        console.log('\n📊 步骤6: 验证私信表中的消息...');

        try {
            // 这里应该查询数据库验证消息是否保存
            // 由于这是客户端测试脚本，我们只能通过日志来验证
            console.log('💡 请检查服务器日志，确认以下信息：');
            console.log('   1. "中奖系统消息已保存到私信表" 日志');
            console.log('   2. 数据库中 private_messages 表是否有新记录');
            console.log('   3. 消息类型为 2（系统消息）');
            console.log('   4. 发送者为 1000（系统角色）');

            this.addTestResult('私信表验证', true, '请手动检查数据库和日志');
        } catch (error) {
            console.log('❌ 验证私信表失败:', error.message);
            this.addTestResult('私信表验证', false, error.message);
        }
    }

    // 7. 断开连接
    async testDisconnect() {
        console.log('\n🔌 步骤7: 断开连接...');
        try {
            this.ws?.close();
        } catch (error) {
            console.log('断开连接时发生错误:', error.message);
        }
        console.log('✅ 连接已断开');
    }

    // 添加测试结果
    addTestResult(testName, success, message) {
        this.testResults.push({ testName, success, message });
    }

    // 打印测试结果
    printTestResults() {
        console.log('\n📊 测试结果汇总:');
        console.log('='.repeat(60));

        const totalTests = this.testResults.length;
        const passedTests = this.testResults.filter(r => r.success).length;
        const failedTests = totalTests - passedTests;

        this.testResults.forEach(result => {
            const status = result.success ? '✅' : '❌';
            console.log(`${status} ${result.testName}: ${result.message}`);
        });

        console.log('='.repeat(60));
        console.log(`📈 总计: ${totalTests} 个测试`);
        console.log(`✅ 通过: ${passedTests} 个`);
        console.log(`❌ 失败: ${failedTests} 个`);

        if (failedTests === 0) {
            console.log('\n🎉 所有测试通过！中奖消息保存到私信表功能正常工作。');
        } else {
            console.log('\n⚠️ 部分测试失败，请检查相关功能。');
        }

        console.log('\n💡 后续验证步骤：');
        console.log('   1. 检查服务器日志中的"中奖系统消息已保存到私信表"信息');
        console.log('   2. 查询数据库 private_messages 表，确认有新的系统消息记录');
        console.log('   3. 验证消息的 messageType 为 2，senderCharacterId 为 1000');
    }

    // HTTP请求工具方法
    async makeHttpRequest(path, method = 'GET', body = null) {
        return new Promise((resolve, reject) => {
            const options = {
                hostname: CONFIG.server.host,
                port: CONFIG.server.port,
                path: path,
                method: method,
                headers: {
                    'Content-Type': 'application/json'
                }
            };

            const req = http.request(options, (res) => {
                let data = '';
                res.on('data', (chunk) => {
                    data += chunk;
                });
                res.on('end', () => {
                    try {
                        resolve(JSON.parse(data));
                    } catch (e) {
                        reject(new Error('响应解析失败'));
                    }
                });
            });

            req.on('error', (err) => reject(err));
            if (body) req.write(JSON.stringify(body));
            req.end();
        });
    }
}

// 运行测试
(async () => {
    const tester = new CasinoPrivateMessageTester();
    await tester.runTest();
})();
